define(['../vendor/kobako/pixi/anime.js'
    , "../vendor/kobako/pixi/laser.js"
    , "../vendor/kobako/counter.js"
], (anime, laser, Counter) => {

    const weapon_init = {
        bullet: weapon => {
            console.log('switch to bullet')
            weapon.type = 'bullet'
            weapon.cooldown.reset(100)
            // weapon.cooldown.set_max()
        },
        laser: weapon => {
            console.log('switch to laser')
            weapon.type = 'laser'
            weapon.cooldown.reset(150)
            // weapon.cooldown.set_max()
        },
    }

    const spawn_bullets = {
        bullet: (launcher, texture_spawner) => {
            console.log('spawn bullets')
            return [bullet(launcher, texture_spawner)]
        },
        laser: (launcher, texture_spawner) => {
            console.log('spawn lasers')
            const positions = laser.positions_on_line(launcher, launcher.facing_point, 100, 20)
            const laser_sprites = positions.map(p => {
                return laser_sprite(p, texture_spawner)
            })
            // console.log(laser_sprites)
            return laser_sprites
        }
    }

    const ajust_bullets = {
        bullet() {
        },
        laser(launcher, bullets) {
            //reset life span
            bullets.forEach(b => {
                b.reset_life_time()
            })

            //ajust position
            const positions = laser.positions_on_line(launcher, launcher.facing_point, 100, 20)
            bullets.forEach((b, index) => {
                b.x = positions[index].x
                b.y = positions[index].y
            })
        },
    }

    function laser_sprite({ x, y }, texture_spawner) {
        // console.log(x,y)
        const texture = texture_spawner.bullet1()
        const result = new PIXI.Sprite(texture)
        result.x = x
        result.y = y
        anime.time_over_desrtoy_sprite(result, 3, () => {
            result.destroy()
        })
        result.set_ani('laser')
        return result
    }

    function bullet(launcher, texture_spawner) {
        const facing = launcher.facing
        const speed = 10

        // Through the texture spawaner
        const b = new PIXI.Sprite(texture_spawner.bullet1())

        // Setting position
        b.x = launcher.x
        b.y = launcher.y

        // Setting the speed and direction of bullets
        b.vx = 0
        b.vy = 0
        switch (facing) {
            case 0:
                b.vy = -speed
                break
            case 1:
                b.vx = speed
                break
            case 2:
                b.vy = speed
                break
            case 3:
                b.vx = -speed
                break
        }

        anime.loop_anime_sprite(b)

        return b
    }

    class Weapon {
        constructor(launcher, texture_spawner) {
            this.name = 'laser'
            this.pressing = false
            this.bullets = []
            this.booms = []
            this.types = ['bullet', 'laser']
            this.type = 'laser'
            this.launcher = launcher
            this.texture_spawner = texture_spawner
            this.cooldown = new Counter(0)
            this.type_counter = new Counter(this.types.length)
            this.switch_callback = []


            this.switch_by_name('laser')
        }
        change_and_init_weapon_type(name){
            // this.log('Switch to weapon: ' + name)
            this.name = name
            weapon_init[name](this)
            this.switch_callback.forEach(cb => cb(name))
        }
        switch_by_name(name) {
            if (this.types.find(t => t == name) == null) {
                const text = 'You can not switch a invalid weapon called:' + name
                console.error(text)
                // this.log(text)
                return
            }

            this.change_and_init_weapon_type(name)

            // Update the type counter
            for (let i = 0; i < this.types.length; i++) {
                if (this.types[i] == name) {
                    this.type_counter.set(i)
                    break
                }
            }
        }
        switch() { // switch in turn
            this.type_counter.update()
            if (this.type_counter.is_over()) {
                this.type_counter.reset()
            }
            this.change_and_init_weapon_type(this.types[this.type_counter.get()])
        }
        spawn_bullets() {
            if (this.is_cooldown_over()) { // cool down time over
                this.cooldown.reset()
                return spawn_bullets[this.name](this.launcher, this.texture_spawner)
            }
        }
        cooldown_update() {
            this.cooldown.update()
        }
        is_cooldown_over() {
            return this.cooldown.is_over()
        }
        ajust_bullets() {
            return ajust_bullets[this.name](this.launcher, this.bullets)
        }
        switch_by_keyboard(kb) {
            const me = this
            kb.mount_down('q', () => {
                me.switch()
            })
        }
    }

    return {
        init_weapon_system: (player, texture_spawner, logger) => {
            const weapon = new Weapon(player, texture_spawner, logger)
            weapon.switch_callback.push(name => {
                logger.add('Switch to weapon: ' + name)
            })
            player.weapon = weapon
        },

    }
})